
function _$(str){
    return document.getElementById(str);
}

var mineArea = [];
var blockState = [];

var mineRow = 0, maxPointX, mineCol = 0, maxPointY, mineCount = 0;
var levelBlock, levelMine;
var timerID = 0, sec = 0;
var stack = new Array();
var seqBlock = [];

function setBlockState(elem, point, state){
    blockState[point.x][point.y] = state;
    elem.className = "class" + state;
    elem.innerHTML = '';
    switch (state) {
        case 1:
            _$('levelMine').innerHTML = (--levelMine);
            break;
        case 2:
            elem.innerHTML = "?";
            _$('levelMine').innerHTML = (++levelMine);
            break;
        case 3:
            removeEvtFunc();
            return;case 4:
            removeEvtFunc();
            return;case 5:
            --levelBlock;
            if (mineArea[point.x][point.y] > 0) 
                elem.style.background = "url(Images/" + mineArea[point.x][point.y] + ".gif) no-repeat"
            break;
        default:
            break;
    }
    if (levelBlock == mineCount) {
        removeEvtFunc();
        if (timerID != 0) {
            clearInterval(timerID);
            timerID = 0;
        }
        _$("winFace").innerHTML = "state: ^_^";
    }
}


function initMineArea(row, col, mine){
    mineRow = row;
    mineCol = col;
    mineCount = mine;
    maxPointX = row - 1;
    maxPointY = col - 1;
    levelBlock = row * col;
    var html = "<table id='mineTable' cellpadding=0 cellspacing=0>";
    for (var i = 0; i < mineRow; i++) {
        mineArea[i] = [];
        blockState[i] = [];
        html += "<tr>";
        for (var j = 0; j < mineCol; j++) {
            mineArea[i][j] = 0;
            blockState[i][j] = 0;
            html += "<td id=" + i + "_" + j + "  class='class0'></td>";
        }
        html += "</tr>";
    }
    html += "</table>";
    document.getElementById("MineArea").innerHTML = html;
    setMine(mineCount);
    addEventToTable();
}

function addEventToTable(){
    var t = document.getElementById("mineTable");
    
    addEvent(t, "mousedown", mouseClickHandler);
    addEvent(t, "dblclick", dblClickHandler);
    
    document.oncontextmenu = function(evt){
        if (window.event) 
            window.event.returnValue = false;
        else 
            evt.preventDefault();
    }
}



function addEvent(elem, evtName, funcHandler)
{
    if (elem.attachEvent) {
        elem.attachEvent("on" + evtName, funcHandler);
    }
    else 
        if (elem.addEventListener) {
            elem.addEventListener(evtName, funcHandler, false);
        }
        else {
            elem["on" + evtName] = funcHandler;
        }
}



function removeEvtFunc(){
    var t = document.getElementById("mineTable");
    if (t.detachEvent) {
        t.detachEvent("onmousedown", mouseClickHandler);
        t.detachEvent("ondblclick", dblClickHandler);
    }
    else {
        t.removeEventListener("mousedown", mouseClickHandler, false);
        t.removeEventListener("dblclick", dblClickHandler, false);
    }
    showAllMine();
}


function firstClickSetting(p){
    var st = _$('spanTime');
    timerID = setInterval(function(){
        st.innerHTML = ++sec;
    }, 1000);
    levelMine = _$('levelMine').innerHTML = mineCount;
    
    if (mineArea[p.x][p.y] == -1) {
        var rc = mineRow * mineCol;
        var ran = Math.floor(Math.random() * (rc - mineCount));
        
        var temR = parseInt(seqBlock[ran] / mineRow);
        var temC = seqBlock[ran] % mineRow;
        mineArea[temR][temC] = -1;
        var around = getMineAround({
            "x": temR,
            "y": temC
        });
        for (var i = around.rowTop; i <= around.rowBottom; i++) {
            for (var j = around.colLeft; j <= around.colRight; j++) {
                if (mineArea[i][j] != -1) 
                    mineArea[i][j]++;
            }
        }
        var curSeq = p.x * p.y;
        var countAroundMine = 0;
        var around = getMineAround(p);
        for (var i = around.rowTop; i <= around.rowBottom; i++) {
            for (var j = around.colLeft; j <= around.colRight; j++) {
                if (mineArea[i][j] != -1) {
                    mineArea[i][j]--;
                }
                else 
                    countAroundMine++;
            }
        }
        mineArea[p.x][p.y] = countAroundMine - 1;
    }
}


var hasPreClick = false;
var preValue = 0;
function mouseClickHandler(e){
    var evt = window.event || e;
    var td = evt.srcElement || evt.target;
    var r_c = td.id.split('_');
    var point = {
        "x": r_c[0],
        "y": r_c[1]
    };
    
    if (timerID == 0)
        firstClickSetting(point);
    

    if (hasPreClick && preValue != evt.button) {
        if (td.nodeName == "TD" && blockState[point.x][point.y] == 5) {
            checkAroundArea(point);
        }
    }
    if (evt.button == 0 || evt.button == 1) {
        hasPreClick = true;
        preValue = evt.button;
        setTimeout(function(){
            hasPreClick = false;
        }, 300);
    }

    

    if (td.nodeName == "TD" && (evt.button == 0 || evt.button == 1)) {
        if (blockState[point.x][point.y] < 3)
        {
            var num = mineArea[point.x][point.y];
            if (num == -1) {
                setBlockState(td, point, 4);
            }
            else 
                if (num > 0) {
                    setBlockState(td, point, 5);
                }
                else {
                    setBlockState(td, point, 5);
                    stack.push(point);
                    expandBlankArea();
                }
        }
    }

    

    if (td.nodeName == "TD" && evt.button == 2) {
        if (blockState[point.x][point.y] == 5) //已翻开
            return;
        else { //未翻开
            var state = blockState[point.x][point.y] + 1;
            state = state <= 2 ? state : 0;
            setBlockState(td, point, state);
        }
    }

}


function dblClickHandler(e){
    var evt = e || window.event;
    var td = evt.srcElement || evt.target;
    var r_c = td.id.split('_');
    var point = {
        "x": r_c[0],
        "y": r_c[1]
    };
    if (td.nodeName == "TD" && blockState[point.x][point.y] == 5) {
        checkAroundArea(point);
    }
}


function checkAroundArea(p){
    var aroundMineCount = 0;
    var around = getMineAround(p);
    for (var i = around.rowTop; i <= around.rowBottom; i++) {
        for (var j = around.colLeft; j <= around.colRight; j++) {
            if (blockState[i][j] == 1) {
                if (mineArea[i][j] == -1) {
                    aroundMineCount++;
                }
                else {
                    setBlockState(_$(i + '_' + j), {"x": i,"y": j}, 3);
                    return;
                }
            }
        }
    }
    
    if (mineArea[p.x][p.y] == aroundMineCount) {
        for (var i = around.rowTop; i <= around.rowBottom; i++) {
            for (var j = around.colLeft; j <= around.colRight; j++) {
                if (blockState[i][j] == 0)
                {
                    if (mineArea[i][j] == 0) {
                        stack.push({"x": i,"y": j});
                        expandBlankArea();
                    }
                    if (mineArea[i][j] > 0) {
                        var td = _$('' + i + '_' + j);
                        setBlockState(td, {"x": i,"y": j}, 5);
                    }
                }
            }
        }
    }
}



function setMine(mine){
    var rc = mineRow * mineCol;
    if (rc <= mine) {
        alert("too much mine!!!");
        return;
    }
    for (var k = 0; k < rc; k++) {
        seqBlock[k] = k;
    }
    var ranNum, temNum;
    for (var i = rc - 1, j = rc - mine; i >= j; i--) {
        ranNum = Math.floor(Math.random() * (i + 1));
        temNum = seqBlock[i];
        seqBlock[i] = seqBlock[ranNum];
        seqBlock[ranNum] = temNum;
    }
    
    var temR, temC;
    for (var q = rc - 1, k = rc - mine; q >= k; q--) {
        temR = parseInt(seqBlock[q] / mineCol);
        temC = seqBlock[q] % mineCol;
        mineArea[temR][temC] = -1;
        var around = getMineAround({
            "x": temR,
            "y": temC
        });
        for (var i = around.rowTop; i <= around.rowBottom; i++) {
            for (var j = around.colLeft; j <= around.colRight; j++) {
                if (mineArea[i][j] != -1) 
                    mineArea[i][j]++;
            }
        }
    }
}


function getMineAround(point){
    row = parseInt(point.x);
    col = parseInt(point.y);
    var around = {};
    around.rowTop = (row == 0 ? 0 : row - 1);
    around.rowBottom = (row == maxPointX ? maxPointX : row + 1);
    around.colLeft = (col == 0 ? 0 : col - 1);
    around.colRight = (col == maxPointY ? maxPointY : col + 1);
    return around;
}


function expandBlankArea(){
    while (stack.length > 0) {
        var p = stack.pop();
        var around = getMineAround(p);
        for (var i = around.rowTop; i <= around.rowBottom; i++) {
            for (var j = around.colLeft; j <= around.colRight; j++) {
                if (blockState[i][j] == 0)
                {
                    var td = _$(i + '_' + j);
                    setBlockState(td, {
                        "x": i,
                        "y": j
                    }, 5);
                    if (mineArea[i][j] == 0)
                        stack.push({
                            "x": i,
                            "y": j
                        });
                }
            }
        }
    }
}


function setMineArea(){
    var a = _$("m_r").value;
    var b = _$("m_c").value;
    var c = _$("m_m").value;
    _$('levelMine').innerHTML = c;
    if (timerID != 0) {
        clearInterval(timerID);
    }
	timerID = 0;
    _$('spanTime').innerHTML = sec = 0;
	_$("winFace").innerHTML = "state: -.-";
    initMineArea(a, b, c);
}


function showAllMine(){
    for (var i = 0; i < mineRow; i++) {
        for (var j = 0; j < mineCol; j++) {
            if (blockState[i][j] == 1 && mineArea[i][j] != -1) {
                _$(i + "_" + j).style.background = "url(Images/mine3.png) no-repeat center";
            }
            if (blockState[i][j] != 1 && blockState[i][j] != 4 && mineArea[i][j] == -1) {
                _$(i + "_" + j).style.background = "url(Images/mine.png) no-repeat center";
            }
        }
    }
}
